//
//  WNLoginVC.swift
//  WalkNovel
//
//  Created by Kevin on 2023/7/4.
//

import UIKit
import HandyJSON
import RxSwift
import RxCocoa
import KeychainAccess
import AuthenticationServices
import GoogleSignIn
import FBSDKLoginKit

class WNLoginVC: WNBaseVC {
    
    lazy var logoBg: UIImageView = {
        let image = UIImageView(image: UIImage(named: "logo_bg"))
        image.contentMode = .scaleAspectFill
        return image
    }()

    lazy var closeBtn: UIButton = {
        let btn = UIButton(type: .custom)
        btn.setImage(UIImage.init(named: "login_close"), for: .normal)
        btn.rx.tap.bind { [weak self] in
            self?.dismiss(animated: true, completion: {
                self?.disClosure?()
            })
        }.disposed(by: rx.disposeBag)
        return btn
    }()
    
    lazy var logoImage: UIImageView = {
        let image = UIImageView(image: UIImage(named: "login_logo"))
        image.wn_cornerWithBorder(8)
        return image
    }()
    
    lazy var appName: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .init(named: "red_FE6390")
        label.font = .init(name: "PingFangSC-Medium", size: 24)
        label.text = "WalkNovel"
        return label
    }()
    
    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .init(named: "gray_666666")
        label.font = .wn_font(name: .bold, size: 18)
        label.text = "Meet you next favorite book"
        return label
    }()
    
    lazy var tipsLabel: UILabel = {
        let label = UILabel()
        label.textColor = .init(named: "gray_999999")
        label.font = .wn_font(name: .regular, size: 12)
        label.text = "You are currently a visitor account. In order to protect your account security and avoid the loss of reading records. Please log in to continue reading. After logging in, your visitor account will be merged with your login account, interests and rights will be preserved."
        label.numberOfLines = 0
        return label
    }()

    lazy var agreeBtn: UIButton = {
        var btn = UIButton(type: .custom)
        btn.setImage(UIImage(named: "setting_feedback_chose_gray"), for: .normal)
        btn.setImage(UIImage(named: "setting_select"), for: .selected)
        btn.imageEdgeInsets = .init(top: 3, left: 3, bottom: 3, right: 3)
        btn.isSelected = true
        btn.rx.tap.bind { [weak self] in
            btn.isSelected = !btn.isSelected
        }.disposed(by: rx.disposeBag)
        return btn
    }()
    
    lazy var privacyView: IQTextView = {
        let view = IQTextView()
        view.font = .wn_font(name: .bold, size: 12)
        view.showsVerticalScrollIndicator = false
        view.wn_appendLinkString(string: "If you continue,you agree to the ")
        view.wn_appendLinkString(string: "Service Agreement", withURLString: WNConfigure.WNURL.wn_Agreement)
        view.wn_appendLinkString(string: " and ")
        view.wn_appendLinkString(string: "Privacy Policy", withURLString: WNConfigure.WNURL.wn_Privacy)
        view.textColor = .init(named: "gray_999999")
        view.linkTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.init(named: "gray_666666")!]
        view.isEditable = false
        view.delegate = self
        view.contentInset = .init(top: -10, left: 0, bottom: 0, right: 0)
        return view
    }()
    
    lazy var appleBtn: UIButton = {
        let btn = UIButton(type: .custom)
        btn.setTitle(" Sign in with Apple", for: .normal)
        btn.titleLabel?.font = .wn_font(name: .bold, size: 16)
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel?.textAlignment = .center
        btn.rx.tap.bind { [weak self] in
            self?.touchAppleBtn()
        }.disposed(by: rx.disposeBag)
        btn.backgroundColor = WNColor.Fade().left2right(.init(width: scaleWidth(240), height: 44))
        btn.wn_cornerWithBorder(22)
        return btn
    }()
    
    lazy var fbBtn: UIButton = {
        let btn = UIButton.init(type: .custom)
        btn.setImage(UIImage(named: "login_facebook"), for: .normal)
        btn.rx.tap.bind { [weak self] in
            self?.touchFacebookBtn()
        }.disposed(by: rx.disposeBag)
//        btn.isHidden = true
        return btn
    }()
    
    lazy var goBtn: UIButton = {
        let btn = UIButton.init(type: .custom)
        btn.setImage(UIImage(named: "login_google"), for: .normal)
        btn.rx.tap.bind { [weak self] in
            self?.touchGoogleBtn()
        }.disposed(by: rx.disposeBag)
        btn.isHidden = true
        return btn
    }()
    
    lazy var lineView: UIView = {
        let view = UIView()
        view.backgroundColor = .white
        return view
    }()
    
    var disClosure: ReturnClosure?
        
    var emailStr = ""
    
    var verStr = ""
    
    var pwStr = ""
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        WNHUD.wn_hide()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewConfig() {
        wn_hidNavView()
        view.addSubview(logoBg)
        view.addSubview(closeBtn)
        view.addSubview(logoImage)
        view.addSubview(appName)
        view.addSubview(titleLabel)
        view.addSubview(tipsLabel)
        
        view.addSubview(agreeBtn)
        view.addSubview(privacyView)
        view.addSubview(lineView)
        view.addSubview(appleBtn)
        view.addSubview(fbBtn)
        view.addSubview(goBtn)
        
        logoBg.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        closeBtn.snp.makeConstraints { make in
            make.top.equalTo(StatusBarHeight)
            make.left.equalTo(12)
            make.width.height.equalTo(32)
        }
        logoImage.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(StatusBarHeight+84)
            make.width.height.equalTo(64)
        }
        appName.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(logoImage.snp.bottom).offset(16)
            make.height.equalTo(29)
        }
        titleLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(appName.snp.bottom).offset(10)
            make.height.equalTo(25)
        }
        tipsLabel.snp.makeConstraints { make in
            make.left.equalTo(22)
            make.right.equalTo(-22)
            make.top.equalTo(titleLabel.snp.bottom).offset(22)
        }
        agreeBtn.snp.makeConstraints { make in
            make.left.equalTo(18)
            make.bottom.equalTo(-48-TabBarMargin)
            make.width.height.equalTo(20)
        }
        privacyView.snp.makeConstraints { make in
            make.top.equalTo(agreeBtn.snp.top).offset(3)
            make.left.equalTo(agreeBtn.snp.right).offset(-2)
            make.right.equalTo(-22)
            make.height.equalTo(45)
        }
        lineView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(-188-TabBarMargin)
            make.width.equalTo(75)
            make.height.equalTo(1)
        }
        appleBtn.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(privacyView.snp.top).offset(-scaleWidth(100))
            make.width.equalTo(scaleWidth(240))
            make.height.equalTo(44)
        }
        fbBtn.snp.makeConstraints { make in
            make.top.equalTo(appleBtn.snp.bottom).offset(44)
            make.left.equalTo(appleBtn.snp.left).offset(44)
            make.width.height.equalTo(44)
        }
        goBtn.snp.makeConstraints { make in
            make.top.equalTo(appleBtn.snp.bottom).offset(44)
            make.right.equalTo(appleBtn.snp.right).offset(-44)
            make.width.height.equalTo(44)
        }
    }
    
    override func dataConfig() {
        pageName = "Login"
    }
}

extension WNLoginVC: UITextViewDelegate {
    
    func shakeAnimation() {
        let animation = CABasicAnimation.init(keyPath: "transform.translation.x")
        animation.duration = 0.1
        animation.fromValue = NSNumber(floatLiteral: -5)
        animation.toValue = NSNumber(floatLiteral: 5)
        animation.autoreverses = true
        agreeBtn.layer.add(animation, forKey: nil)
    }
    
    func tapLoginBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("Please read and agree to check the protocol first")
            return
        }
        guard WNRegex(WNRegex.passwordPattern).match(input: pwStr) else {
            wn_toast("Enter between 6 to 20 characters\nContain at least one number and one letter")
            return
        }
    }
    
    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        wn_pushWebVC(URL.absoluteString, URL.absoluteString == WNConfigure.WNURL.wn_Privacy ? "Privacy Policy" : "Service Agreement")
        return false
    }
}

extension WNLoginVC {
    
    /// 登录成功统一处理
    func loginSuc(_ type: String, _ model: UserDetailModel?, _ msg: String) {
        if let m = model {
            WNBuriedManager.shared.signIn(type, m.userId ?? "")
            saveUser(user: m)
            setKeyUserId(m.userId ?? "")
            WNSingleData.shared.userGold = m.gold
            wn_toast(msg)
            NotificationCenter.default.post(name: WNNotiName.loginNoti, object: self)
            dismiss(animated: true)
        }else {
            wn_toast(msg)
        }
    }
    
    /// 苹果登录
    func loginByAppleId(_ userId: String, _ openId: String) {
        WNHUD.wn_showLoading()
        provider_login.rx.request(.appleLogin(userId, openId))
            .asObservable().mapModel(BaseModel<UserDetailModel>.self)
            .subscribe(onNext: { [weak self] (model) in
                guard model.code == 0 else {
                    self?.wn_toast(model.msg ?? "")
                    return
                }
                self?.loginSuc("Apple", model.data, "Login success")
            }, onError: { [weak self] (error) in
                self?.wn_toast("Check the network connection")
            }).disposed(by: rx.disposeBag)
    }
    
    /// FB登录
    func loginByFacebook(_ token: String, _ userId: String, _ name: String, _ email: String, _ headUrl: String) {
        WNHUD.wn_showLoading()
        provider_login.rx.request(.facebookLogin(token, userId, name, email, headUrl))
            .asObservable().mapModel(BaseModel<UserDetailModel>.self)
            .subscribe(onNext: { [weak self] (model) in
                guard model.code == 0 else {
                    self?.wn_toast(model.msg ?? "")
                    return
                }
                self?.loginSuc("FB", model.data, "Login success")
            }, onError: { [weak self] (error) in
                self?.wn_toast("Check the network connection")
            }).disposed(by: rx.disposeBag)
    }
}

extension WNLoginVC {
    
    @objc func touchAppleBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("Please read and agree to check the protocol first")
            return
        }
        let controller = ASAuthorizationController(authorizationRequests: [ ASAuthorizationAppleIDProvider().createRequest()])
        controller.delegate = self
        controller.presentationContextProvider = self
        controller.performRequests()
    }
    
    func touchFacebookBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("Please read and agree to check the protocol first")
            return
        }
        LoginManager().logOut()
        LoginManager().logIn(permissions: ["public_profile", "email"], from: self) { [weak self] (signInResult, error) in
            guard error == nil else { return }
            guard let signInResult = signInResult else { return }
            if signInResult.isCancelled {
                self?.wn_toast("You canceled the authorization")
            }else {
                let userID = signInResult.token?.userID ?? ""
                Profile.loadCurrentProfile { profile, error in
                    guard error == nil else { return }
                    guard let profile = profile else { return }
                    let token = signInResult.token?.tokenString ?? ""
                    let userId = profile.userID
                    let email = profile.email ?? ""
                    let name = profile.name ?? ""
                    let avatar = profile.imageURL(forMode: .square, size: .init(width: 200, height: 200))?.absoluteString ?? ""
                    self?.loginByFacebook(token, userId, name, email, avatar)
                }
            }
        }
    }
    
    func touchGoogleBtn() {
        guard agreeBtn.isSelected else {
            shakeAnimation()
            wn_toast("Please read and agree to check the protocol first")
            return
        }
        let gidConfig = GIDConfiguration(clientID: WNConfigure.Google.clientID, serverClientID: "")
        GIDSignIn.sharedInstance.configuration = gidConfig
        GIDSignIn.sharedInstance.signIn(withPresenting: self) { [weak self] (result, error) in
            guard error == nil else { return }
            guard let user = result?.user else { return }
            let userID = user.userID ?? ""
            let email = user.profile?.email ?? ""
            let name = user.profile?.name ?? ""
            let avatar = user.profile?.imageURL(withDimension: 320)?.absoluteString ?? ""
            self?.wn_toast("userId = \(userID)\n email = \(email)\n name = \(name)\n avatar = \(avatar)", 3)
        }
    }
}

extension WNLoginVC: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if authorization.credential is ASAuthorizationAppleIDCredential {
            let credential = authorization.credential as! ASAuthorizationAppleIDCredential
            let userId = credential.user
            guard !userId.isEmpty,
                  let idTokenData = credential.identityToken,
                  let authCodeData = credential.authorizationCode,
                  let idToken = String(data: idTokenData, encoding: .utf8), !idToken.isEmpty,
                  let authCode = String(data: authCodeData, encoding: .utf8), !authCode.isEmpty else
            {
                self.failCompletion()
                return
            }
            loginByAppleId(userId, idToken)
        }else if authorization.credential is ASPasswordCredential {
            failCompletion()
        }else {
            failCompletion("授權錯誤")
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        var errMsg: String = "Unknown authentication error"
        switch error {
        case ASAuthorizationError.canceled:
            errMsg = "You Canceled the authorization"
        case ASAuthorizationError.failed:
            errMsg = "Authorization failed"
        case ASAuthorizationError.invalidResponse:
            errMsg = "Invalid authorization"
        case ASAuthorizationError.notHandled:
            errMsg = "Failed to process authorization"
        case ASAuthorizationError.unknown:
            errMsg = "Unknown authorization"
        default:
            break
        }
        failCompletion(errMsg)
    }
    
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        if let windowOption = UIApplication.shared.delegate?.window {
            if let window = windowOption {
                return window
            }
        }
        return UIWindow(frame: Screen.bounds)
    }
    
    func failCompletion(_ str: String = "Login failed") {
        wn_toast(str)
    }
}
